package com.xjnt.base.support.admin.controller;

import java.util.List;
import java.util.Map;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.RealmSecurityManager;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jfinal.plugin.activerecord.Record;
import com.xjnt.base.support.admin.entity.Permission;
import com.xjnt.base.support.admin.entity.Role;
import com.xjnt.base.support.admin.service.PermissionService;
import com.xjnt.base.support.admin.service.RoleService;
import com.xjnt.base.support.admin.shiro.realm.ShiroJdbcRealm;
import com.xjnt.frameworks.annotation.AutoInject;
import com.xjnt.frameworks.annotation.Router;
import com.xjnt.frameworks.core.CRUDController;
import com.xjnt.frameworks.exception.BusinessException;
import com.xjnt.frameworks.web.message.RetDataMsg;
import com.xjnt.frameworks.web.message.RetMsg;

@Router(name="/system/admin/role", view="/admin/role")
public class RoleController extends CRUDController<Role, RoleService> {
	
	@AutoInject
	private RoleService roleService;

	@AutoInject
	private PermissionService permissionService;

	@Override
	protected String getBizName() {
		return "角色";
	}
	
	@Override
	protected Class<Role> getClazz() {
		return Role.class;
	}

	@Override
	protected RoleService getService() {
		return roleService;
	}

	/**
	 * 分配权限
	 */
	public void allocPermission(){
		//参数保持传递
		keepPara();
		render("allocPermission.html");	
	}
	
	public void doAllocPermission(){
		RetMsg retMsg = new RetMsg();
		try{
			String[] permIds = getPara("allocPermIds") == null ? null : getPara("allocPermIds").split(",");
			if(null != permIds){ // 目标分配权限表示空
				List<Permission> newRolePerms = permissionService.findByIds(permIds);
				//原分配权限
				String targetRoleId = getPara("roleId");
				List<Permission> originalRolePerms = permissionService.findByRoleId(targetRoleId);
				//定义原权限与新权限的交集
				List<Permission> retainPerms = Lists.newArrayList();
				retainPerms.addAll(originalRolePerms);
				retainPerms.retainAll(newRolePerms);
				// 从新的权限中去掉原来已增加过的权限
				newRolePerms.removeAll(retainPerms);
				// 原权限中去掉交集权限，就是需要删除的权限
				originalRolePerms.removeAll(retainPerms);
				if(!originalRolePerms.isEmpty()){
					getService().removePermissions(targetRoleId, originalRolePerms);
					updPermCache();
				}
				//保存已分配的新权限
				if(!newRolePerms.isEmpty()){
					getService().allocPermission(targetRoleId, newRolePerms);
					updPermCache();
				}
			} else {
				String targetRoleId = getPara("roleId");
				getService().removeAllPermission(targetRoleId);
				updPermCache();
			}
			retMsg.pushOk("分配权限成功");
			renderJson(retMsg);
		} catch (Exception ex){
			throw new BusinessException("分配角色", "发生异常：", ex);
		}
	}
	
	public void treePermission(){
		RetDataMsg dataMsg = new RetDataMsg(true);
		try{
			List<Map<String, Object>> lstTree = null;
			List<Record> lstPermPlat = permissionService.findAllPlatformPermission();
			if(null == lstPermPlat || lstPermPlat.isEmpty()){ // 没有定义权限
				dataMsg.pushError("没有定义权限数据");
			} else {
				dataMsg.pushOk("权限树获取成功");
				String targetRoleId = getPara("roleId");
				List<Permission> lstAllocedPerm = permissionService.findByRoleId(targetRoleId);
				lstTree = Lists.newArrayList();
				for (Record platform : lstPermPlat) {
					Map<String, Object> platformNode = Maps.newHashMap();
					platformNode.put("uuid", platform.getStr("uuid"));
					platformNode.put("permid", platform.getStr("permid"));
					platformNode.put("name", platform.getStr("name"));
					platformNode.put("permtype", platform.getInt("type"));
					platformNode.put("parentid", null);
					platformNode.put("checked", this.isAlloced(lstAllocedPerm, platform.getStr("permid")));
					lstTree.add(platformNode);
					// 组装模块
					String platformId = platform.getStr("uuid");
					List<Record> lstPermMod = permissionService.findModulePermissionByPlatId(platformId);
					for (Record module : lstPermMod) {
						Map<String, Object> moduleNode = Maps.newHashMap();
						moduleNode.put("uuid", module.getStr("uuid"));
						moduleNode.put("permid", module.getStr("permid"));
						moduleNode.put("name", module.getStr("name"));
						moduleNode.put("permtype", module.getInt("type"));
						moduleNode.put("parentid", platformId);
						moduleNode.put("checked", this.isAlloced(lstAllocedPerm, module.getStr("permid")));
						lstTree.add(moduleNode);
						//组装菜单
						String moduleId = module.getStr("uuid");
						List<Record> lstPermMenu = permissionService.findMenuPermissionByModId(moduleId);
						for (Record menu : lstPermMenu) {
							Map<String, Object> menuNode = Maps.newHashMap();
							menuNode.put("uuid", menu.getStr("uuid"));
							menuNode.put("permid", menu.getStr("permid"));
							menuNode.put("name", menu.getStr("name"));
							menuNode.put("permtype", menu.getInt("type"));
							menuNode.put("parentid", moduleId);
							menuNode.put("checked", this.isAlloced(lstAllocedPerm, menu.getStr("permid")));
							lstTree.add(menuNode);
							//组装功能
							String menuId = menu.getStr("uuid");
							List<Record> lstPermFunc = permissionService.findFunctionPermissionByMenuId(menuId);
							for (Record func : lstPermFunc) {
								Map<String, Object> funcNode = Maps.newHashMap();
								funcNode.put("uuid", func.getStr("uuid"));
								funcNode.put("permid", func.getStr("permid"));
								funcNode.put("name", func.getStr("name"));
								funcNode.put("permtype", func.getInt("type"));
								funcNode.put("parentid", menuId);
								funcNode.put("checked", this.isAlloced(lstAllocedPerm, func.getStr("permid")));
								lstTree.add(funcNode);
							}
						}
					}
				}
				dataMsg.setRows(lstTree);
			}
			renderJson(dataMsg);
		} catch(Exception ex){
			throw new BusinessException("查询权限", "发生异常：", ex);
		}
	}
	
	private boolean isAlloced(List<Permission> lstAllocedPerm, String permid){
		boolean flag = false;
		for (Permission permission : lstAllocedPerm) {
			String allocId = permission.getStr(Permission.PK_ID);
			if(allocId.equalsIgnoreCase(permid)){
				flag = true;
				break;
			}
		}
		return flag;
	}
	
	private void updPermCache(){
		RealmSecurityManager securityManager = (RealmSecurityManager) SecurityUtils.getSecurityManager();
		ShiroJdbcRealm shiroJdbcRealm = (ShiroJdbcRealm) securityManager.getRealms().iterator().next();
		shiroJdbcRealm.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipal());
	}
}
